/**
 * @file iap.c
 * @brief 
 * @author wangh (wanghuan3037@fiberhome.com)
 * @version 1.0
 * @date 2020-11-16
 * @copyright Copyright (c) 2020  烽火通信
 ***************************************************************
 * @par 修改日志:
 * <table>
 * <tr><th>Date       <th>Version  <th>Author  <th>Description
 * <tr><td>2020-11-16 <td>1.0      <td>wangh   <td>内容
 * </table>
 */ 
#include "iap.h"
#include "bsp.h"
#include "easyflash.h"

#undef LOG_LEVEL_
#define LOG_LEVEL_ 	LOG_LVL_VERBOSE
#include "bsp_log.h"


typedef void (*iapfun)(void);

/**
 * @brief 跳转到应用程序段
 * @param  appxaddr    用户代码起始地址
 */
void iap_load_app(uint32_t appxaddr)
{
    /* 检查栈顶地址是否合法 */
    if( ((*(volatile uint32_t *)appxaddr) & 0x2FFE0000) == 0x20000000 )
    {
        /* 用户代码区第二个字为程序开始地址 */
        iapfun jump2app = (iapfun) *(volatile uint32_t*) (appxaddr + 4);

        /* 初始化APP堆栈指针 */
        __set_MSP(*(volatile uint32_t*) appxaddr);

//        SCB->VTOR = APP_START_ADDR;
        jump2app();
    }
    else
    {
        log_e( "iap_load_app appxaddr invaild...\r\n" );
    }
}


int8_t iap_download_prepare( void )
{
    EfErrCode result = EF_NO_ERR;

    result = ef_erase_bak_app( APP_SIZE );
    if (result != EF_NO_ERR)
    {
        log_e( "ef_erase_bak_app error(%d)\r\n", result );
        return BSP_ERROR_IAP;
    }

    /* 可以关闭其他任务，进入升级模式 */

    return BSP_SUCCESS;
}

int8_t iap_download( uint8_t *data, uint32_t size, uint32_t *cur_size, uint32_t total_size )
{
    EfErrCode result = EF_NO_ERR;

    result = ef_write_data_to_bak( data, size, cur_size, total_size);
    if (result == EF_NO_ERR)
        return BSP_SUCCESS;
    else
    {
        log_e( "ef_write_data_to_bak error(%d)\r\n", result );
        return BSP_ERROR_IAP;
    }
}


int8_t iap_upgrade_prepare( void )
{
    EfErrCode result = EF_NO_ERR;
    uint8_t upgrade_flag = IAP_UPGRADE_ON;

    result = ef_set_env_blob( "iap_need_copy_app", &upgrade_flag, 1 );
    if (result == EF_NO_ERR)
    {
        log_d( "iap download over, start goto boot...\r\n" );
        vTaskDelay(10);
        NVIC_SystemReset();
        return BSP_SUCCESS;
    }
    else
    {
        log_e( "ef_set_env_blob error(%d)\r\n", result );
        return BSP_ERROR_IAP;
    }
}


int8_t iap_upgrade_result( uint8_t * iap_upgrade_flag )
{
	EfErrCode result = EF_NO_ERR;
	uint8_t upgrade_flag = 0;

    if (ef_get_env_blob( "iap_need_copy_app", &upgrade_flag, 1, NULL ) != 1)
        log_e( "ef_set_env iap_need_copy_app error\r\n" );
	*iap_upgrade_flag = upgrade_flag;
	upgrade_flag = IAP_UPGRADE_OK;
    result = ef_set_env_blob( "iap_need_copy_app", &upgrade_flag, 1 );
    if (result != EF_NO_ERR)
    {
        log_e( "ef_set_env_blob error(%d)\r\n", result );
        return BSP_ERROR_IAP;
    }
	return BSP_SUCCESS;
}

void iap_upgrade( void )
{
    uint8_t upgrade_flag = 0;

    if (ef_get_env_blob( "iap_need_copy_app", &upgrade_flag, 1, NULL ) != 1)
        log_e( "ef_set_env iap_need_copy_app error\r\n" );

    log_d( "iap_need_copy_app = %d\r\n", upgrade_flag );

    if (upgrade_flag == IAP_UPGRADE_ON)
    {
        uint32_t bak_app_start_addr = ef_get_bak_app_start_addr();
        if( ((*(volatile uint32_t *)bak_app_start_addr)&0x2FFE0000) == 0x20000000 ) /* 检查备份程序是否有效 */
        {
            if ( EF_NO_ERR != ef_erase_user_app( APP_START_ADDR, APP_SIZE ) )
            {
                log_e( "ef_erase_user_app error\r\n" );
                NVIC_SystemReset();
            }

            if ( EF_NO_ERR != ef_copy_app_from_bak( APP_START_ADDR, APP_SIZE ) )
            {
                log_e( "ef_copy_app_from_bak error\r\n" );
                NVIC_SystemReset();
            }
			upgrade_flag = IAP_UPGRADE_OK;   /* 升级完成/无需升级 */
        }
		else
		{
			upgrade_flag = IAP_UPGRADE_FAIL;   /* 升级失败 */
		}
        
        ef_set_env_blob( "iap_need_copy_app", &upgrade_flag, 1 );
    }

    __ASM volatile("cpsid i");  /* 关闭所有中断 */
    log_d( "iap_load_app(%08X) now...\r\n", APP_START_ADDR );
    iap_load_app( APP_START_ADDR );
}

int8_t iap_upgrade_result_get( char * upgrade_result)
{
    uint8_t upgrade_flag = 0;

    if (ef_get_env_blob( "iap_need_copy_app", &upgrade_flag, 1, NULL ) == 2)
    {
        *upgrade_result = 0;
    }
    else
    {
        *upgrade_result = 1;
    }
    return BSP_SUCCESS;
}


/*********** (C) COPYRIGHT 2020 FiberHome *****END OF FILE****/

